// hdu5735
// 题意：
// 给定一课n(<=2^16)个节点的有根树，每个节点有一个权值(<=2^16)，现在对
// 任意s属于{1, 2, 3, ..., n}, 需要找到一个点的序列v[1], v[2], ..., v[m]满足：
//   1. v[1] = s 且 v[i]是v[i-1]的祖先(1<i<=m)
//   2. 要使 f(s)=w[v[1]] + sigma(w[v[i]] opt w[v[i-1]], i=2..m)，最大, 
//      opt操作可以是AND, OR, XOR。
// 最后求S=(i*f(i), i=1..n) % (10^9 + 7)
//
// 题解：
// 考虑序列上, 令 dp[s] = f[s] - w[s]
//   dp[i] = max{ dp[j] + w[i] opt w[j]}, j < i。
// 我们可以将w分为高低八位，维护一个这样的二维数组
//   ds(x, y)，x表示某个w[j]的高8位，y表示某个w[i]的低8位，
//   ds(x, y) = max{dp[j]+ [w[i]低8位] opt [w[j]低8位]}
// 有了这个数组，每次算dp[i]就可以2^8枚举j的高8位来算，
// 并且知道dp[i]后更新这个数组也只需要2^8来更新。
//
// 到了树上和链上差不多，因为每次更新ds数组的时候只会更新其中一维，
// 所以对这一维做一个可持久化（备份）就行。
//
// run: time -p $exec < 1002.in > out
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using vtype = unsigned int;
int const maxn = 1 << 17;
int const maxm = 1 << 9;
vtype const mo = 1000000007;
vtype dp[maxn + 4];
vtype * ds[maxm];
vtype pool[maxn + maxn][maxm];
int alloc;

std::vector<int> tree[maxn];
int w[maxn + 4];
int n;
char input_opt[10];

void add_edge(int u, int v)
{
	tree[u].push_back(v);
	tree[v].push_back(u);
}

vtype* new_array(vtype* src = NULL)
{
	if (!src) {
		memset(pool[alloc], -1, sizeof(pool[0]));
	} else {
		memcpy(pool[alloc], src, sizeof(pool[0]));
	}
	return pool[alloc++];
}

void init()
{
	alloc = 0;
	for (int i = 0; i <= n; i++) tree[i].clear();
	memset(dp, 0, sizeof(dp));
	for (int i = 0; i < maxm; i++) ds[i] = new_array();
}

vtype calc(int u, int v)
{
	if (input_opt[0] == 'X') return u ^ v;
	else if (input_opt[0] == 'A') return u & v;
	return u | v;
}

// dp[i] = max{dp[j] + (wh[i] opt wh[j]) << 8 + wl[i] opt wl[j]}
// wh for high 8 bits for w, wl for low 8 bits for w
void dfs(int u, int father)
{
	int whu = (w[u] >> 8) & 255;
	int wlu = w[u] & 255;
	// iterator wh[j]
	for (int i = 0; i < (1 << 8); i++) {
		if (ds[i][wlu] == vtype(-1)) continue;
		vtype tmp = ds[i][wlu] + (calc(whu, i) << 8);
		dp[u] = std::max(dp[u], tmp);
	}
	// update ds, iterator wl[i]
	vtype* back = ds[whu];
	ds[whu] = new_array(back);
	for (int i = 0; i < (1 << 8); i++) {
		vtype tmp = dp[u] + calc(wlu, i);
		if (ds[whu][i] == vtype(-1) || tmp > ds[whu][i]) ds[whu][i] = tmp;
	}
	for (auto v : tree[u]) {
		if (v == father) continue;
		dfs(v, u);
	}
	ds[whu] = back;
}

int main()
{
	int T; std::scanf("%d", &T);
	while (T--) {
		std::scanf("%d", &n);
		std::scanf("%s", input_opt);
		init();
		for (int i = 1; i <= n; i++) std::scanf("%d", &w[i]);
		for (int i = 2, x; i <= n; i++) {
			std::scanf("%d", &x);
			add_edge(i, x);
		}

		dp[1] = 0;
		dfs(1, 0);

		long long ans = 0;
		for (long long i = 1; i <= n; i++) {
			ans += (i * (dp[i] + w[i])) % mo;
			ans %= mo;
		}

		printf("%lld\n", ans);
	}
}

